package club.janna.rpcdemo.codec;

import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * java序列化编解码
 */
public class JavaSerialCodec implements Codec {

    /**
     * | head(2) | length(4) | body |
     * @param request
     * @return
     */
    @Override
    public byte[] encode(Object request) {
        if(request == null)
            return null;
        ByteOutputStream bos = new ByteOutputStream();
        ObjectOutputStream objectOutputStream = null;
        byte[] bytes = null;
        try {
            objectOutputStream = new ObjectOutputStream(bos);
            objectOutputStream.writeObject(request);
            bytes = bos.getBytes();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            bos.close();
        }
        if(bytes == null)
            return null;
        int len = bytes.length;
        byte[] frame = new byte[len + 6];
        // 报文头
        frame[0] = (byte) 0xCA;
        frame[1] = (byte) 0xFE;
        // 报文长度
        frame[2] = (byte) (len >> 24);
        frame[3] = (byte) (len >> 16 & 0xFF);
        frame[4] = (byte) (len >> 8 & 0xFF);
        frame[5] = (byte) (len & 0xFF);
        // 报文内容
        System.arraycopy(bytes, 0, frame, 6, len);
        return frame;
    }

    @Override
    public <T> T decode(byte[] bytes) {
        if(bytes == null)
            return null;
        ByteInputStream bis = new ByteInputStream(bytes, bytes.length);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(bis);
            return (T) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
